package com.zenchn.controller;

import com.zenchn.annotation.OperLog;
import com.zenchn.entity.*;
import com.zenchn.enums.OperLogActionEnum;
import com.zenchn.enums.TownRuralCategoryCodeEnum;
import com.zenchn.exception.CheckException;
import com.zenchn.external.service.AmapService;
import com.zenchn.model.TSysAreas;
import com.zenchn.model.TSysAreasExample;
import com.zenchn.service.AreasService;
import io.swagger.annotations.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;

/**
 * 区域控制器
 * 
 * @author dingxinfa
 * @date 2020-04-20
 **/

@RestController
@RequestMapping(value = "areas")
@Api(value = "区域功能相关接口",tags="系统管理-区域配置")
@RequiresPermissions("area:setting")
public class AreasController {

	private final String MODULE="系统管理>区域配置";


	@Resource
    private AreasService areaService;

	@Resource
	private AmapService amapService;

	/**
	 * 区域数据列表
	 *
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "区域数据列表", isSaveRequestData = false)
	@ApiOperation(value = "区域数据列表", notes = "区域数据列表")
	@ApiImplicitParam(dataType = "String", name = "parentCode", value = "上级区域编码，12位全码")
	@GetMapping(value = "/list")
	@RequiresPermissions("area:setting")
	public ResponseEntity<HttpDataResult<List<TSysAreasVO>>> list(
            @RequestParam(required = false, value = "parentCode", defaultValue = "0") String parentCode,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpDataResult<List<TSysAreasVO>> result = new HttpDataResult<>(request.getRequestURI());

		List<TSysAreas> areaList=areaService.selectByParentId(parentCode);
		List<TSysAreasVO> areasVOList=new ArrayList<>();
		for (TSysAreas areas:areaList){
			TSysAreasVO areasVO=new TSysAreasVO();
			BeanUtils.copyProperties(areas,areasVO);
			if (null!=areas.getCategory() && "".equals(areas.getCategory().trim())){
				areasVO.setCategoryName(TownRuralCategoryCodeEnum.getDesc(areas.getCategory()));
			}

			if (Integer.parseInt(areas.getGrade())<5){
				areasVO.setChildren(new ArrayList<>());
			}

			areasVOList.add(areasVO);
		}
		result.setData(areasVOList);

		result.setMessage("获取区域数据列表成功.");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);
	}


	/***
	 * 区域状态变更
	 * @param code
	 * @param isEnable
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module=MODULE,action= OperLogActionEnum.UPDATE,detail="区域状态变更",isSaveRequestData=true)
	@ApiOperation(value = "区域状态变更", notes = "区域状态变更")
	@ApiImplicitParams({
			@ApiImplicitParam(dataType = "String", name = "code", value = "区域编码(全码)", required = true),
			@ApiImplicitParam(dataType = "Boolean", name = "isEnable", value = "是否启用", required = true)
	})
	@PutMapping(value = "/statusChange")
	@RequiresPermissions("area:setting:modify")
	public ResponseEntity<HttpDataResult<TSysAreas>> statusChange(
            @RequestParam(value = "code") String code,
            @RequestParam( value = "isEnable") Boolean isEnable,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
		HttpDataResult<TSysAreas> result = new HttpDataResult<>(request.getRequestURI());
		TSysAreas areas= areaService.selectByPrimaryKey(code);
		if (null==areas){
			throw new CheckException("区域编码无效，请检查！");
		}

		if (!isEnable){
			TSysAreasExample areasExample=new TSysAreasExample();
			areasExample.createCriteria().andCodeLike(areas.getShortCode()+"%").andGradeGreaterThan(areas.getGrade()).andIsEnableEqualTo(true);
			if (areaService.countByExample(areasExample)>0){
				throw new CheckException("下级区域已开启，不能关停当前区域状态！");
			}
		}


		areas.setIsEnable(isEnable);
		areaService.updateByPrimaryKeySelective(areas);
		result.setData(areas);

		result.setMessage("Ok.");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);

	}


	/***
	 * 获取城乡分类编码列表
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module=MODULE,action= OperLogActionEnum.QUERY,detail="城乡分类编码列表")
	@ApiOperation(value = "城乡分类编码列表", notes = "城乡分类编码列表")
	@GetMapping(value = "/categoryList")
	public ResponseEntity<HttpDataResult<List<Map<String,String>>>> categoryList(
            HttpServletRequest request, HttpServletResponse response) throws Exception{
		HttpDataResult<List<Map<String,String>>> result = new HttpDataResult<>(request.getRequestURI());

		result.setData(TownRuralCategoryCodeEnum.getList());
		result.setMessage("OK");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);
	}


	/***
	 * 区域详情 （修改页获取数据）
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module=MODULE,action= OperLogActionEnum.QUERY,detail="区域详情 （修改页获取数据）")
	@ApiOperation(value = "区域详情 （修改页获取数据）", notes = "区域详情 （修改页获取数据）")
	@ApiImplicitParam(dataType = "String", name = "code", value = "区域编码", required = true)
	@GetMapping(value = "/detail")
	public ResponseEntity<HttpDataResult<Map<String,Object>>> detail(
            @RequestParam(value = "code") String code,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
		HttpDataResult<Map<String,Object>> result = new HttpDataResult<>(request.getRequestURI());
		Map<String,Object> resultData=new HashMap<>(16);

		TSysAreas areas=areaService.selectByPrimaryKey(code);
		resultData.put("areas", areas);
		//获取父级路径
		if (null != areas.getParentCode() && !"".equals(areas.getParentCode().trim())) {
			LinkedList<TSysAreas> fullCascadeList = areaService.findFullCascade(areas.getParentCode());
			resultData.put("parentList", assembleSysAreasVO(fullCascadeList));
		}


		result.setData(resultData);
		result.setMessage("OK");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);
	}


	/***
	 * 组装整合已选择级联区域数据
	 * @param areasList
	 * @return
	 */
	private List<TSysAreasVO> assembleSysAreasVO(LinkedList<TSysAreas> areasList){
		List<TSysAreasVO> areasVOList=new ArrayList<>();

		TSysAreas areas=areasList.pollFirst();
		if (null!=areas) {
			TSysAreasVO areasVO=new TSysAreasVO();
			BeanUtils.copyProperties(areas,areasVO);
			if (!areasList.isEmpty()) {
				areasVO.setChildren(assembleSysAreasVO(areasList));
			}
			areasVOList.add(areasVO);
		}
		return areasVOList;
	}

	/**
	 * 新增区域保存提交
	 * @param areaDO
	 * @param results
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module=MODULE,action= OperLogActionEnum.INSERT,detail="新增区域保存提交")
	@ApiOperation(value = "新增区域保存提交", notes = "新增区域保存提交")
	@ApiParam(type = "AreaAddDO", name = "areaDO", value = "区域新增映射对象", required = true)
	@PostMapping(value = "/addSubmit")
	@RequiresPermissions("area:setting:add")
	public ResponseEntity<HttpDataResult<String>> addSubmit(
            @RequestBody @Valid AreaAddDO areaDO, BindingResult results,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
		HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

		if (results.hasErrors()){
			throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
		}

		TSysAreas areas=new TSysAreas();
		areas.setCategory(areaDO.getCategory());
		areas.setIsEnable(areaDO.getIsEnable());
		areas.setMemo(areaDO.getMemo());

		areas.setName(areaDO.getName());

		if (null!=areaDO.getParentCode() && null!=areaDO.getParentShortCode()){
			if(areaDO.getParentCode().indexOf(areaDO.getParentShortCode())!=0){
				throw new CheckException("上级区域全码与上级区域简码匹配有误，请检查！");
			}

			TSysAreas parentAreas=areaService.selectByPrimaryKey(areaDO.getParentCode());
			if (null==parentAreas){
				throw new CheckException("上级区域编码有误，无法查到相应区域，请检查！");
			}

			areas.setShortCode(parentAreas.getShortCode()+areaDO.getEditCode());
			areas.setParentCode(parentAreas.getCode());
			areas.setParentShortCode(parentAreas.getShortCode());

			areas.setGrade(String.valueOf(Integer.parseInt(parentAreas.getGrade())+1));
			//省
			areas.setProvince(parentAreas.getProvince());
			//市
			areas.setCity(parentAreas.getCity());
			//区县
			areas.setDistrict(parentAreas.getDistrict());
			//街道、乡镇
			areas.setTown(parentAreas.getTown());
			//村、社区
			areas.setVillage(parentAreas.getVillage());

			switch (areas.getGrade()){
				case "1":
					areas.setProvince(areas.getName());
					break;
				case "2":
					areas.setCity(areas.getName());
					break;
				case "3":
					areas.setDistrict(areas.getName());
					break;
				case "4":
					areas.setTown(areas.getName());
					break;
				case "5":
					areas.setVillage(areas.getName());
					break;
				default:
					break;
			}
			//全称
			areas.setFullName(parentAreas.getFullName()+areas.getName());
		}else{
			areas.setShortCode(areaDO.getEditCode());
			areas.setParentCode("0");
			areas.setParentShortCode("0");

			areas.setGrade("1");

			areas.setProvince(areas.getName());
			//全称
			areas.setFullName(areas.getName());
		}

		areas.setCode(String.format("%-12s", areas.getShortCode()).replace(' ', '0'));

		if (null!=areaService.selectByPrimaryKey(areas.getCode())){
			throw new CheckException("当前区域编码系统已存在，无法重复新增！");
		}

		if (!areaService.verifyName(areas.getParentCode(),null,areas.getName())){
			throw new CheckException("区域名称重复，无法提交！");
		}

		LatLon latLon=amapService.getLatLonByAddress(areas.getFullName());
		if (null!=latLon){
			areas.setLongitude(new BigDecimal(Double.toString(latLon.getLon())));
			areas.setLatitude(new BigDecimal(Double.toString(latLon.getLat())));
		}

		areaService.insert(areas);

		result.setData(areas.getCode());

		result.setMessage("新增区域成功！");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);

	}


	/**
	 * 修改区域保存提交
	 * @param areaDO
	 * @param results
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module=MODULE,action= OperLogActionEnum.UPDATE,detail="修改区域保存提交")
	@ApiOperation(value = "修改区域保存提交", notes = "修改区域保存提交")
	@ApiParam(type = "AreaModifyDO", name = "areaDO", value = "区域修改映射对象", required = true)
	@PutMapping(value = "/modifySubmit")
	@RequiresPermissions("area:setting:modify")
	public ResponseEntity<HttpDataResult<String>> modifySubmit(
            @RequestBody @Valid AreaModifyDO areaDO, BindingResult results,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
		HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

		if (results.hasErrors()){
			throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
		}

		TSysAreas areas= areaService.selectByPrimaryKey(areaDO.getCode());
		if (null==areas){
			throw new CheckException("区域全码无效，请检查！");
		}
		if (!areaService.verifyName(areas.getParentCode(),areas.getCode(),areaDO.getName())){
			throw new CheckException("区域名称重复，无法提交！");
		}
		if (!areaDO.getIsEnable()){
			TSysAreasExample areasExample=new TSysAreasExample();
			areasExample.createCriteria().andCodeLike(areas.getShortCode()+"%").andGradeGreaterThan(areas.getGrade()).andIsEnableEqualTo(true);
			if (areaService.countByExample(areasExample)>0){
				throw new CheckException("下级区域已开启，不能关停当前区域状态！");
			}
		}

		areas.setName(areaDO.getName());
		areas.setIsEnable(areaDO.getIsEnable());
		areas.setCategory(areaDO.getCategory());
		areas.setMemo(areaDO.getMemo());


		switch (areas.getGrade()){
			case "1":
				areas.setProvince(areas.getName());
				break;
			case "2":
				areas.setCity(areas.getName());
				break;
			case "3":
				areas.setDistrict(areas.getName());
				break;
			case "4":
				areas.setTown(areas.getName());
				break;
			case "5":
				areas.setVillage(areas.getName());
				break;
			default:
				break;
		}

		StringBuilder fullName=new StringBuilder();
		if (null!=areas.getProvince()){
			fullName.append(areas.getProvince());
		}
		if (null!=areas.getCity()){
			fullName.append(areas.getCity());
		}
		if (null!=areas.getDistrict()){
			fullName.append(areas.getDistrict());
		}
		if (null!=areas.getTown()){
			fullName.append(areas.getTown());
		}
		if (null!=areas.getVillage()){
			fullName.append(areas.getVillage());
		}
		//全称
		areas.setFullName(fullName.toString());

		if (null==areas.getLongitude() || null==areas.getLatitude() ||new BigDecimal(0).equals(areas.getLongitude()) ||new BigDecimal(0).equals(areas.getLatitude())) {
			LatLon latLon = amapService.getLatLonByAddress(areas.getFullName());
			if (null != latLon) {
				areas.setLongitude(new BigDecimal(Double.toString(latLon.getLon())));
				areas.setLatitude(new BigDecimal(Double.toString(latLon.getLat())));
			}
		}

		areaService.updateByPrimaryKey(areas);

		result.setData(areas.getCode());

		result.setMessage("修改区域成功！");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);

	}


	/***
	 * 验证同区域下下级区域名称唯一性
	 * @param code
	 * @param parentCode
	 * @param name
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module=MODULE,action= OperLogActionEnum.CHECK,detail="验证同区域下下级区域名称唯一性",isSaveRequestData=true)
	@ApiOperation(value = "验证同区域下下级区域名称唯一性", notes = "验证同区域下下级区域名称唯一性")
	@ApiImplicitParams({
			@ApiImplicitParam(dataType = "String", name = "code", value = "当前区域编码(全码)", required = false),
			@ApiImplicitParam(dataType = "String", name = "parentCode", value = "上级区域编码(全码)", required = false),
			@ApiImplicitParam(dataType = "String", name = "name", value = "区域名称", required = true)
	})
	@GetMapping(value = "/verifyName")
	public ResponseEntity<HttpDataResult<Boolean>> verifyName(
            @RequestParam(required = false, value = "code") String code,
            @RequestParam(required = false,  value = "parentCode",defaultValue = "0") String parentCode,
            @RequestParam( value = "name") String name,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
		HttpDataResult<Boolean> result = new HttpDataResult<>(request.getRequestURI());

		result.setData(areaService.verifyName(parentCode,code,name));

		result.setMessage("OK.");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);

	}




	/**
	 * 获取下级区域列表
	 * @param parentCode   上级区域编码
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@OperLog(module=MODULE,action= OperLogActionEnum.QUERY,detail="获取下级区域列表")
	@ApiOperation(value = "获取下级区域列表", notes = "获取下级区域列表")
	@ApiImplicitParam(dataType = "String", name = "parentCode", value = "上级区域编码(全码)", required = false)
	@GetMapping(value = "/subAreasData")
	public ResponseEntity<HttpDataResult<List<TSysAreasVO>>> subAreasData (
            @RequestParam(required = false, value = "parentCode",defaultValue = "0") String parentCode,
            HttpServletRequest request, HttpServletResponse response) throws Exception{

		HttpDataResult<List<TSysAreasVO>> result = new HttpDataResult<>(request.getRequestURI());


		List<TSysAreas> areaList=areaService.selectByParentId(parentCode);

		List<TSysAreasVO> areasVOList=new ArrayList<>();


		for (TSysAreas areas:areaList){
			TSysAreasVO areasVO=new TSysAreasVO();
			BeanUtils.copyProperties(areas,areasVO);

			if (Integer.parseInt(areas.getGrade())<4){
				areasVO.setChildren(new ArrayList<>());
			}
			if (Integer.parseInt(areas.getGrade())<5) {
				areasVOList.add(areasVO);
			}
		}

		result.setData(areasVOList);

		result.setMessage("获取级联区域数据子集成功.");
		result.setStatus(HttpStatus.OK.value());
		return new ResponseEntity<>(result, HttpStatus.OK);

	}
}